/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "编译声明代码.h"
#include <core/设备内存缓存.h>
#include <file_文件名数据.h>
//#include <几何计算.h>

#include <字符串数值互换.h>
#include "节点数据声明.h"



static std::vector<E_JIT_FunParam>  g函数变量指针;

typedef void* (*ptr_JIT_Fun_vec3_alloc变量)(uint64 num);
typedef void(*ptr_JIT_Fun_vec3_resize变量)(void* val, uint64 num);

static std::map<std::string, std::string[2]> g内联函数代码;
static bool g内联函数代码改变 = true;


static std::map<C_节点树*, C_并行计算环境> g_并行环境;

C_并行计算环境::C_并行计算环境() {

}

C_并行计算环境::~C_并行计算环境() {

}

C_并行计算环境& C_并行计算环境::f_get(C_节点树* tree) {
	return g_并行环境[tree];
}

void C_并行计算环境::f_更新代码() {
	g内联函数代码改变 = true;
}



std::vector<std::string> S_JIT_函数指针名称::g函数指针名称 = {
	//"f_JIT_Fun_vec3_alloc变量",
	//"f_JIT_Fun_vec3_resize变量",
};

std::vector<std::string> S_JIT_函数指针名称::g返回类型 = {
	//"void*",
	//"void",
};

std::vector<std::string> S_JIT_函数指针名称::g参数类型 = {
	//"uint64 num",
	//"void* val, uint64 num",
};


std::string f_代码构建_函数和变量指针() {
	static std::string code;
	if (code.size()) {
		return code;
	}
	
	uint32 num = S_JIT_函数指针名称::g函数指针名称.size();
	for (uint32 i = 0; i < num; ++i) {
		code += "typedef "+ S_JIT_函数指针名称::g返回类型[i] +"(*ptr_" + S_JIT_函数指针名称::g函数指针名称[i] + ")(" + S_JIT_函数指针名称::g参数类型[i] + ");\n";
		code += "static ptr_" + S_JIT_函数指针名称::g函数指针名称[i] + " " + S_JIT_函数指针名称::g函数指针名称[i] + ";\n";
	}

	return code;
}

std::vector<E_JIT_FunParam>& f_代码构建_取参数函数指针() {
	return g函数变量指针;
}

std::string f_代码构建_JIT函数指针初始化() {
	static std::string code;
	if (code.size()) return code;

	code += DEF_S(DEF_全局变量_节点运行类型状态定义)" = nullptr;\n";

	code += "extern \"C\" { __declspec(dllexport)  void f_fnPtr_init( E_JIT_FunParam* 参数); }\n";
	code += "void f_fnPtr_init(E_JIT_FunParam* 参数){\n";
	//code += "for(uint32 i=0; i<参数数量; ++i){\n";
	for (uint32 i = 0; i < S_JIT_函数指针名称::g函数指针名称.size(); ++i) {
		code += S_JIT_函数指针名称::g函数指针名称[i] + " = (ptr_" + S_JIT_函数指针名称::g函数指针名称[i] + ")(参数["+ f_整数值转字符串(i) + "].m_data); \n";
	}
	//code += "}\n";


	code += DEF_S(DEF_全局变量_g_执行状态离线_)" = (bool*)" + DEF_指针转字符串(&S_节点数据::g_开启节点帧更新) + ";\n";
	code += "}\n";

	return code;
}

void f_代码构建_添加JIT初始化函数指针(std::string 定义名称,  std::string 返回类型, std::string 参数类型, void* fp) {
	//S_JIT_函数指针名称::g函数指针类型定义名称.push_back(定义名称);
	S_JIT_函数指针名称::g函数指针名称.push_back(定义名称);
	S_JIT_函数指针名称::g返回类型.push_back(返回类型);
	S_JIT_函数指针名称::g参数类型.push_back(参数类型);

	E_JIT_FunParam e{};
	e.m_data = fp;
	g函数变量指针.push_back(e);
}

void f_代码构建_添加JIT初始化变量指针(std::string 定义名称, std::string 返回类型, std::string 参数类型, void* fp) {

}

std::string f_代码构建_预定义类型() {
	static std::string code;
	if (code.size()) return code;
	
	code += "struct S_边;\n";
	code += "struct S_面;\n";
	code += "struct S_Mesh;\n";
	code += "struct S_多边形;\n";
	code += "struct S_曲线;\n";
	//code += "struct S_多边形面;\n";
	code += "struct S_物体;\n";
	code += "struct S_纹理;\n";
	code += "struct S_设备环境;\n";
	
	code += DEF_S(struct C_节点基类)";\n";
	code += DEF_S(struct C_插座基类)";\n";
	code += DEF_S(struct S_Props)";\n";
	code += DEF_S(struct S_字体)";\n";
	code += DEF_S(struct S_网格自定义属性)";\n";
	code += DEF_S(struct S_GPU计算)";\n";
	code += DEF_S(struct S_GPU参数槽)";\n";
	
	code += "#define DEF_Max(a,b) (((a) > (b)) ? (a) : (b))\n";
	code += "#define DEF_Min(a,b) (((a) < (b)) ? (a) : (b))\n";

	//S_边Array;

	return code;
}

std::string f_代码构建_创建vec3数组(std::string name) {
	std::string code;
	code = "void* " + name + " = " + DEF_S(f_JIT_Fun_vec3_alloc) + "(false, 0, 0, {}, {}, {});\n";
	return code;
}

std::string f_代码构建_取vec3数组数量(std::string& 变量名称, std::string var) {
	变量名称 += "_vec3数组数量";
	std::string code = "uint32 " + 变量名称 + " = ";
	code = DEF_S(f_JIT_Fun_vec3_size);
	code += "(" + var + ")";
	return code;
}

std::string f_代码构建_vec3数组分配(std::string name, std::string num) {
	std::string 分配代码;
	分配代码 += "void* " + name + " = " + DEF_S(f_JIT_Fun_vec3_alloc) + "(false, " + num + ", 0, {}, {}, {});\n";
	return 分配代码;
}

std::string f_代码构建_释放vec3数组(const std::string& name) {
	std::string 释放 = DEF_S(f_JIT_Fun_vec3_free);
	释放 += "(" + name + ");\n";
	return 释放;
}

std::string f_代码构建_新建变量忽略负数(const std::string& 变量, std::string& 新变量名称) {
	std::string code;
	新变量名称 += "变量忽略负数";
	code = "uint32 " + 新变量名称 + " = " + 变量 + " < 0 ? " + "0 : " + 变量 + ";\n";
	return code;
}

std::string f_代码构建_多边形边数组数量(std::string& 变量名称, const std::string& 多边形代码) {
	变量名称 += "_多边形边数组数量";
	std::string code = "uint32 " + 变量名称 + " = ";
	code += DEF_S(f_多边形_边数量);
	code += "(" + 多边形代码 + ");\n";
	return code;
}

std::string f_代码构建_创建vec3_Array(std::string& 新变量名称, const std::string& 数量) {
	std::string code = "S_Vec3Array* " + 新变量名称 + " = " + DEF_S(f_vec3_array_alloc) + "(" + 数量 + ");\n";
	return code;
}

static std::map<uint32, std::string> DBUGE_记录申请;
static std::map<uint32, std::string> DBUGE_记录释放;
static std::mutex 记录锁;

std::string f_代码构建_创建Array(E_值类型 类型, const std::string& 数量) {
	
	switch (类型) {
		case E_值类型::e_Type_Bool_1D:
			return DEF_S((S_BoolArray*)f_core_array_new_type)"(" + 数量 + ", " + DEF_S(E_值类型::e_Type_Bool_1D) + ");\n";
		case E_值类型::e_Type_I8_1D:
			return DEF_S((S_I8Array*)f_core_array_new_type)"(" + 数量 + ", " + DEF_S(E_值类型::e_Type_I8_1D) + ");\n";
		case E_值类型::e_Type_F32_1D:
			return DEF_S((S_F32Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(float32) + "), false, true);\n";
		case E_值类型::e_Type_I32_1D:
			return DEF_S((S_I32Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(int32) + "), false, true);\n";


		case E_值类型::e_Type_UI32_1D:
			return DEF_S((S_UI32Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(uint32) + "), false, true);\n";
		case E_值类型::e_Type_UI32_2D:
			return DEF_S((S_UI32Array2D*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_UI32Array*) + "), true, true);\n";


		case E_值类型::e_Type_Vec2_1D:
			return DEF_S((S_Vec2Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(vec2) + "), false, true);\n";
		case E_值类型::e_Type_uVec2_1D:
			return DEF_S((S_uVec2Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(uvec2) + "), false, true);\n";
		case E_值类型::e_Type_Vec3_1D:
			return DEF_S((S_Vec3Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(vec3) + "), false, true);\n";
		case E_值类型::e_Type_iVec2_1D:
			return DEF_S((S_iVec2Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(ivec2) + "), false, true);\n";
		case E_值类型::e_Type_iVec3_1D:
			return DEF_S((S_iVec3Array*)f_core_array_new_type)"(" + 数量 + ", " + DEF_S(E_值类型::e_Type_iVec3_1D) + ");\n";


		case E_值类型::e_Type_iVec3_2D:
			return DEF_S((S_iVec3Array2D*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_iVec3Array*) + "), true, true);\n";
		case E_值类型::e_Type_Vec3_2D:
			return DEF_S((S_Vec3Array2D*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_Vec3Array*) + "), true, true);\n";


		case E_值类型::e_Type_Vec4_1D:
			return DEF_S((S_Vec4Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(vec4) + "), false, true);\n";
		case E_值类型::e_Type_iVec4_1D:
			return DEF_S((S_iVec4Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(ivec4) + "), false, true);\n";


		case E_值类型::e_Type_Mat4X4_1D:
			return "(S_Mat44Array*)f_core_array_new(" + 数量 + ", sizeof(Mat44f), false, true);\n";


		case E_值类型::e_Type_Bounding_1D:
			return DEF_S((S_CubeArray*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_Cube) + "), false, true);\n";


		case E_值类型::e_Type_多边形边1D:
			return DEF_S((S_边Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_边*) + "), false, true);\n";
		case E_值类型::e_Type_多边形_1D:
			return DEF_S((S_多边形Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_多边形*) + "), false, true);\n";


		case E_值类型::e_Type_多边形元素:
			return DEF_S((S_多边形元素*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_面*) + "), false, true);\n";
		case E_值类型::e_Type_多边形元素1D:
			return DEF_S((S_多边形元素Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_多边形元素*) + "), false, true);\n";
		case E_值类型::e_Type_ArrayRef:
			return DEF_S(f_core_array_new_type)"(" + 数量 + ", " + DEF_S(E_值类型::e_Type_ArrayRef) + ");\n";
			//return DEF_S((S_多边形元素Array*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_多边形元素*) + "), false);\n";

		case E_值类型::e_Type_纹理_1D:
			return DEF_S((S_TexArray*)f_core_array_new)"(" + 数量 + ", sizeof(" + DEF_S(S_纹理*) + "), false, true);\n";

		case E_值类型::e_Type_Array:
			return DEF_S((S_Array*)f_core_array_new)"(" + 数量 + ", sizeof(uint8), false, true); \n";
	}

	return "";
}

std::string f_代码构建_销毁数组(std::string 新变量名称) {
	std::string code = "f_core_array_free((S_Array*)" + 新变量名称 + ");\n";
	return code;
}

std::string f_代码构建_Array数组数量(std::string var) {
	return "((" + var + ")->count)";
}

std::string f_代码构建_Array元素大小(std::string var) {
	return DEF_S(f_core_array_get_elt_size)"((S_Array*)" + var + ")";
}

bool f_代码构建_是否为单值浮点(E_值类型 type) {
	switch (type) {
		case E_值类型::e_Type_F32:
		case E_值类型::e_Type_F64:
		case E_值类型::e_Type_F32_1D:
		case E_值类型::e_Type_F64_1D:
			return true;
	}
	return false;
}

bool f_代码构建_是否为单值数组浮点(E_值类型 type) {
	switch (type) {
		//case E_值类型::e_Type_F32:
		//case E_值类型::e_Type_F64:
		case E_值类型::e_Type_F32_1D:
		case E_值类型::e_Type_F64_1D:
			return true;
	}
	return false;
}

bool f_代码构建_是否为矢量浮点(E_值类型 type) {
	switch (type) {
		case E_值类型::e_Type_Vec2:
		case E_值类型::e_Type_Vec3:
		case E_值类型::e_Type_Vec4:
			return true;
	}
	return false;
}

bool f_代码构建_是否为矢量数组浮点(E_值类型 type) {
	switch (type) {
		case E_值类型::e_Type_Vec2_1D:
		case E_值类型::e_Type_Vec3_1D:
		case E_值类型::e_Type_Vec4_1D:
			return true;
	}
	return false;
}

E_值类型 f_代码构建_多维数组元素(E_值类型 type) {
	switch (type) {
		case E_值类型::e_Type_UI32_2D: return E_值类型::e_Type_UI32_1D;

		case E_值类型::e_Type_Vec3_2D: return E_值类型::e_Type_Vec3_1D;
		case E_值类型::e_Type_iVec3_2D: return E_值类型::e_Type_iVec3_1D;
	}
	return E_值类型::e_Type_None;
}

E_值类型 f_代码构建_多维数组(E_值类型 type) {
	switch (type) {
		case E_值类型::e_Type_UI32_2D: return E_值类型::e_Type_UI32_1D;

		case E_值类型::e_Type_Vec3_2D: return E_值类型::e_Type_Vec3_1D;
		case E_值类型::e_Type_iVec3_2D: return E_值类型::e_Type_iVec3_1D;
	}
	return E_值类型::e_Type_None;
}

std::string f_代码构建_i32GPU变量(S_Props& 属性) {
	std::string code = "i32_GParam.i32Ptr[";
	code += f_整数值转字符串(属性.m_GPU缓存[0].m_Mem.m_偏移);
	code += "]";
	return code;
}

void f_代码构建_内联函数声明定义(const std::string keyName, const std::string& 函数声明, const std::string& 函数代码) {
	g内联函数代码[keyName][0] = 函数声明;
	g内联函数代码[keyName][1] = 函数代码;
	g内联函数代码改变 = true;
}

bool f_代码构建_内联函数保存到文件() {
	std::string path = S_节点数据::g_工程文件节点代码路径 + "Inline_fun.h";

	if (g内联函数代码改变 || f_file_文件是否存在(path) == false) {
		std::string hpp;

		
		FILE* f = fopen(path.c_str(), "w");
		if (f) {
			hpp += "#pragma once \n";
			hpp += "extern ";
			hpp += DEF_S(DEF_编译全局可调参数)";\n";

			hpp += "extern ";
			hpp += DEF_S(DEF_全局变量_节点运行类型状态定义)";\n";


			for (auto k : g_并行环境) {
				hpp += k.second.m_常量定义;
			}

			for (auto k : g内联函数代码) {
				hpp += k.second[0];
			}
			for (auto k : g内联函数代码) {
				hpp += k.second[1];
			}

			f_file_保存文本(f, hpp);
			fclose(f);
		}
	}

	g内联函数代码改变 = false;
	return g内联函数代码.size();
}

void f_代码构建_清除代码缓存() {
	g内联函数代码.clear();
	g内联函数代码改变 = true;
}




void f_代码构建_自定义属性设置(S_网格自定义属性& 属性, const S_Props& 类型名称, S_Props& 属性名称, const S_Props& 分布方式) {
	auto typeName = f_prop_enumName(类型名称);

	//if (typeName == u"f32") {
	//	属性.m_Type = E_值类型::e_Type_F32_1D;
	//}
	//else if (typeName == u"i32") {
	//	属性.m_Type = E_值类型::e_Type_I32_1D;
	//}
	//else if (typeName == u"ui32") {
	//	属性.m_Type = E_值类型::e_Type_UI32_1D;
	//}
	//else if (typeName == u"vec2") {
	//	属性.m_Type = E_值类型::e_Type_Vec2_1D;
	//}
	//else if (typeName == u"vec3") {
	//	属性.m_Type = E_值类型::e_Type_Vec3_1D;
	//}
	//else if (typeName == u"vec4") {
	//	属性.m_Type = E_值类型::e_Type_Vec4_1D;
	//}
	//else if (typeName == u"ivec2") {
	//	属性.m_Type = E_值类型::e_Type_iVec2_1D;
	//}
	//else if (typeName == u"ivec3") {
	//	属性.m_Type = E_值类型::e_Type_iVec3_1D;
	//}
	//else if (typeName == u"ivec4") {
	//	属性.m_Type = E_值类型::e_Type_iVec4_1D;
	//}
	if (typeName == u"f32") {
		属性.m_Type = E_值类型::e_Type_F32;
	}
	else if (typeName == u"i32") {
		属性.m_Type = E_值类型::e_Type_I32;
	}
	else if (typeName == u"ui32") {
		属性.m_Type = E_值类型::e_Type_UI32;
	}
	else if (typeName == u"vec2") {
		属性.m_Type = E_值类型::e_Type_Vec2;
	}
	else if (typeName == u"vec3") {
		属性.m_Type = E_值类型::e_Type_Vec3;
	}
	else if (typeName == u"vec4") {
		属性.m_Type = E_值类型::e_Type_Vec4;
	}
	else if (typeName == u"ivec2") {
		属性.m_Type = E_值类型::e_Type_iVec2;
	}
	else if (typeName == u"ivec3") {
		属性.m_Type = E_值类型::e_Type_iVec3;
	}
	else if (typeName == u"ivec4") {
		属性.m_Type = E_值类型::e_Type_iVec4;
	}

	属性.m_Name = &f_prop_LineStr(属性名称);
	属性.m_分布方式 = f_prop_enum(分布方式);

	属性.m_多边形 = nullptr;
}

std::string f_代码构建_着色器引用数据声明() {
	std::string code;
	code += "R_GlobalParameter_I32 i32_GParam = R_GlobalParameter_I32(gGlobalParam.m_AddressI32);\n";
	code += "R_GlobalParameter_UI32 ui32_GParam = R_GlobalParameter_UI32(gGlobalParam.m_AddressUI32);\n";
	code += "R_GlobalParameter_F32 f32_GParam = R_GlobalParameter_F32(gGlobalParam.m_AddressF32);\n";
	code += "R_GlobalParameter_Vec2 vec2_GParam = R_GlobalParameter_Vec2(gGlobalParam.m_AddressVec2);\n";
	code += "R_GlobalParameter_Vec3 vec3_GParam = R_GlobalParameter_Vec3(gGlobalParam.m_AddressVec3);\n";
	code += "R_GlobalParameter_Vec4 vec4_GParam = R_GlobalParameter_Vec4(gGlobalParam.m_AddressVec4);\n";

	code += "R_GlobalParameter_iVec2 ivec2_GParam = R_GlobalParameter_iVec2(gGlobalParam.m_AddressiVec2);\n";
	code += "R_GlobalParameter_iVec3 ivec3_GParam = R_GlobalParameter_iVec3(gGlobalParam.m_AddressiVec3);\n";
	code += "R_GlobalParameter_iVec4 ivec4_GParam = R_GlobalParameter_iVec4(gGlobalParam.m_AddressiVec4);\n";

	code += "R_GlobalParameter_UVec2 uvec2_GParam = R_GlobalParameter_UVec2(gGlobalParam.m_AddressUVec2);\n";
	code += "R_GlobalParameter_UVec3 uvec3_GParam = R_GlobalParameter_UVec3(gGlobalParam.m_AddressUVec3);\n";
	code += "R_GlobalParameter_UVec4 uvec4_GParam = R_GlobalParameter_UVec4(gGlobalParam.m_AddressUVec4);\n";

	//code += "R_GlobalParameter_CurevPoint curvePoint_GParam = R_GlobalParameter_CurevPoint(gGlobalParam.m_AddressSampleCurve);\n";
	return code;
}





